前面繁瑣的設定請參考Mark飛大大的文章
然而在Mark飛大大文章的 5.接收階段,
因為flutter firebase messaging版本有變
API的接法也有所變更, 本篇將以後續改動接著處理下去
目前處理的版本 firebase_messaging: ^10.0.6
廢話不多說 直接上code
首先是main.dart檔案 在進入點的時候先 new firebase messaging
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await PushNotificationManager.init();
await UserDefault().init();
runApp(MyApp());
}
接著PushNotificationManager是將FirebaseMessaging再封裝一次
大家也可以選擇自己喜歡的命名
init()裡面先取得權限與拿到FCM token,
接著就是精彩的各種狀態handle
onMessage
onMessageOpenedApp
onBackgroundMessage
getInitialMessage
1. App打開在前景時 Android系統會沒有推播通知
但還是會進onMessage這個function, 有些人會用 flutter_local_notifications處理
這邊用GetX snackbar(因為長得也像推播的橫幅 XDD)
2. 如果APP是關掉(拉掉)狀態的時候點開推播
查了一下stack overflow
class PushNotificationManager {
static Future<void> init() async {
await Firebase.initializeApp();
await requestPermission();
await getToken();
//iOS啟用前台通知
if (Platform.isIOS) {
// Required to display a heads up notification
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
}
//從關掉狀態點開推播
FirebaseMessaging.instance
.getInitialMessage()
.then((RemoteMessage? message) {
if (message != null) {
print("從關掉狀態點開推播");
print('on Resume(getInitial): $message');
pushToPage(message);
}
});
//App打開在前景時
FirebaseMessaging.onMessage.listen((message) {
if (message.notification != null) {
print("-------收到前景推播--------");
print(message.notification!.body);
print(message.notification!.title);
if (Platform.isAndroid) showForegroundFakeNotification(message);
}
});
//App退到背景,當回到App後 或是點了推播通知後
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
//AndroidNotification? android = message.notification?.android;
if (message.notification != null) {
print(message.notification!.body);
print(message.notification!.title);
}
print("App退到背景,當回到App後 或是點了推播通知後");
pushToPage(message);
});
///後台消息
FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
}
static getToken() async {
if (Platform.isIOS) {
String apnstoken = await FirebaseMessaging.instance.getAPNSToken() ?? "";
print("APNSToken: $apnstoken");
}
String fcmToken = await FirebaseMessaging.instance.getToken() ?? "";
print("FCMToken: $fcmToken");
UserDefault().fcmToken = fcmToken;
}
static requestPermission() async {
if (Platform.isIOS) {
NotificationSettings settings =
await FirebaseMessaging.instance.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
print('User granted permission: ${settings.authorizationStatus}');
}
}
}
Future<void> backgroundMessageHandler(RemoteMessage message) async {
print("收到後臺訊息(onBackground): ${message.messageId}");
print("後臺訊息title: ${message.notification!.title}");
print("後臺訊息data: ${message.data.toString()}");
await Firebase.initializeApp();
pushToPage(message);
}
pushToPage(RemoteMessage message) {
//這邊主要處理, 點開系統的推播通知後, 要push進哪一頁
Get.offAll(() => FirstPage(), binding: PagesBind());
}
///安卓在App打開(前景)的時候系統不會有推播通知 利用GetX的snackbar 加一個假的
showForegroundFakeNotification(RemoteMessage message) async {
final title = message.notification?.title ?? "";
final body = message.notification?.body ?? "";
Get.snackbar(
title,
body,
barBlur: 50,
icon: Image.asset('assets/ic_notification.png',
fit: BoxFit.contain, width: 26, height: 26),
duration: const Duration(seconds: 20),
margin: const EdgeInsets.only(top: 4),
onTap: (obj) {
//print(obj);
pushToPage(message);
},
);
}
下一篇將為大家介紹 connectivity_plus
請問如果在沒有開啟 app 的狀態,要怎麼收到通知?
我在 foreground、background 都能收到通知,但只要 APP 整個關掉之後就收不到了。
我的裝置版本是 android9,APP 是還在開發階段,還沒上架到 Play 商店(應該跟這個無關?)
By the way, 我有試過把 priority 設成 high,但一樣沒作用
可以在文章內搜尋
"如果APP是關掉(拉掉)狀態的時候點開推播"
參考一下
或是直接看這篇
https://stackoverflow.com/questions/65056272/how-to-configure-firebase-messaging-with-latest-version-in-flutter
如果是從拉掉狀態點開App 主要還是 FirebaseMessaging.instance.getInitialMessage()
這個function的Future回傳的內容, 去檢查推播訊息
stackoverflow的回答是
做在App首頁的initState方法內
當然你可以放在別的地方作檢查